#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
// #include <X11/Xmu/WinUtil.h>
#include <X11/extensions/XTest.h>

static void dump_window_info( Display *dpy, Window w );
static void print_text_field( Display *dpy, const char *s, XTextProperty *tp );
static void unknown( Display *dpy, Atom actual_type, int actual_format );

int main( int argc, char *argv[] )
{
	Display *display = XOpenDisplay( NULL );

	if( NULL == display ) {
		fprintf( stderr, "open display failed!!\n" );
		exit( EXIT_FAILURE );
	}
	XEvent event;

	bzero( &event, sizeof(XEvent));
	event.type = ButtonPress;
	event.xbutton.button = Button1;
	event.xbutton.same_screen = True;


	/* get info about current pointer position */
	XQueryPointer( display, RootWindow( display, DefaultScreen( display )),
			&event.xbutton.root, &event.xbutton.window,
			&event.xbutton.x_root, &event.xbutton.y_root,
			&event.xbutton.x, &event.xbutton.y,
			&event.xbutton.state );

	event.xbutton.subwindow = event.xbutton.window;

	printf( "stat: %x\n", event.xbutton.state );

	/* walk down through window hierachy to find youngest child */
	while( event.xbutton.subwindow ) {
		dump_window_info( display, event.xbutton.subwindow );
		printf( "rootx: %d, rooty: %d\tx: %d, y %d\n",
				event.xbutton.x_root, event.xbutton.y_root,
				event.xbutton.x, event.xbutton.y );
		event.xbutton.window = event.xbutton.subwindow;
		XQueryPointer( display, event.xbutton.window,
				&event.xbutton.root, &event.xbutton.subwindow,
				&event.xbutton.x_root, &event.xbutton.y_root,
				&event.xbutton.x, &event.xbutton.y,
				&event.xbutton.state );
	}
}

static void dump_window_info( Display *dpy, Window w )
{
	XTextProperty nametp, tp;

	printf( "Window: %lx\n", w );
	if( XGetWMName( dpy, w, &nametp )) {
		print_text_field( dpy, "  Name:  ", &nametp );
		if( nametp.value ) XFree((char *)nametp.value );
	}
	if( XGetWMIconName( dpy, w, &tp )) {
		print_text_field( dpy, "  Icon Name:  ", &tp );
		if( tp.value ) XFree((char *)tp.value );
	}
}

static const char *Nil = "(nil)";
static void unknown( Display *dpy, Atom actual_type, int actual_format )
{
	char *s;

	printf( "<unknown type " );
	if( actual_type == None ) printf( "None" );
	else if((s = XGetAtomName( dpy, actual_type )) != NULL ) {
		fputs( s, stdout );
		XFree( s );
	}
	else {
		fputs( Nil, stdout );
	}
	printf( " (%ld) or format %d>", actual_type, actual_format );
}

static void print_text_field( Display *dpy, const char *s, XTextProperty *tp )
{
	if( tp->encoding == None || tp->format == 0 ) {
		printf( "''" );
		return;
	}

	if( s ) printf( "%s", s );
	if( tp->encoding == XA_STRING && tp->format == 8 ) {
		printf( "%s", tp->value ? (char *)tp->value : Nil );
	}
	else {
		unknown( dpy, tp->encoding, tp->format );
	}
	if( s ) putchar( '\n' );
}

